package ude.univ.esiag.gon.uchiha.reader;

import ude.univ.esiag.gon.uchiha.operation.Operation;
import ude.univ.esiag.gon.uchiha.register.Multicaster;
import ude.univ.esiag.gon.uchiha.subscriber.DataReactor;
import ude.univ.esiag.gon.uchiha.subscriber.Subscriber;
import ude.univ.esiag.gon.uchiha.subscriber.impl.SubscriberImpl;
import ude.univ.esiag.gon.uchiha.topic.SerializableTopic;
import ude.univ.esiag.gon.uchiha.topic.Topic;
import ude.univ.esiag.gon.uchiha.writer.DataWriter;

public class DataReader implements DataReaderListener{
	private SubscriberImpl subscriber;
	private Topic topic;
	private boolean bootstrap = false;
	
	public DataReader(Topic topic) {
		subscriber = DataReactor.newInstance().addListener(this);
		this.topic = topic;
		this.topic.setSubscriber(subscriber);
	}
	
	public void signal(final String topicName) {
		if(!topicName.equals(topic.getName()))
			return;
		new Thread(new Runnable() {
			public void run() {
				Operation op = subscriber.read(topicName);
				if(op == null)
					return;
				traite(op);
			}
		}).start();
	}
	synchronized private void traite(Operation op){
		if(op.getTarget() == Operation.TOPIC){
			if(op.getType() == Operation.IOR){
				String ior = (String)op.getData().getObj();
				Subscriber subscriber = Multicaster.getInstance().ior_to_subscriber(ior);
				topic.getWriter().addSubscriber(subscriber);
			}
			else if(op.getType() == Operation.BOOTSTRAP){
				if(!bootstrap){
					bootstrap = true;
					SerializableTopic topic = (SerializableTopic)op.getData().getObj();
					this.topic.createTopicFromSerializableTopic(topic);
				}
			}
			else if(op.getType() == Operation.CREATE){
				SerializableTopic topic = (SerializableTopic)op.getData().getObj();
				this.topic.addTopic(topic.getSimpleName());
			}
			else if(op.getType() == Operation.CREATES){
				String topicName = (String)op.getData().getObj();
				this.topic.addTopic(topicName);
				if(op.isToReplicate()){
					op.setToReplicate(false);
					topic.getWriter().write(op);
				}
			}
			else if(op.getType() == Operation.GETIOR){
				String ior = (String)op.getData().getObj();
				String topicName = op.getData().getTopicName();
				int index = topicName.indexOf(".");
				String rootName = topicName.substring(0, index);
				Topic topicRoot = Multicaster.getInstance().getTopicByName(rootName);
				Topic topic1 = topicRoot.getTopic(topicName);
				Subscriber subscriber = Multicaster.getInstance().ior_to_subscriber(ior);
				topic1.getWriter().addSubscriber(subscriber);
				String ior1 = topic1.getSubscriberIOR();
				if(ior1 == null){
					SubscriberImpl subscriber1 = topic1.getSubscriber();
					ior1 = Multicaster.getInstance().subscriber_to_ior(subscriber1);
					topic1.setSubscriberIOR(ior1);
				}
				Operation operation = new Operation(topicName, ior1);
				operation.setTarget(Operation.TOPIC);
				operation.setType(Operation.SETIOR);
				operation.setToReplicate(false);
				topic1.getWriter().write(operation);
			}
			else if(op.getType() == Operation.SETIOR){
				String ior = (String)op.getData().getObj();
				String topicName = op.getData().getTopicName();
				int index = topicName.indexOf(".");
				String rootName = topicName.substring(0, index);
				Topic topic = Multicaster.getInstance().getTopicByName(rootName);
				Topic topic1 = topic.getTopic(topicName);
				Subscriber subscriber = Multicaster.getInstance().ior_to_subscriber(ior);
				topic1.getWriter().addSubscriber(subscriber);
			}
		}
		else if(op.getTarget() == Operation.CACHE){
			if(op.getType() == Operation.WRITE){
				topic.modifieCache(op.getData().getObj());
				if(op.isToReplicate()){
					op.setToReplicate(false);
					topic.getWriter().write(op);
				}
			}
			if(op.getType() == Operation.READ){
				Subscriber subscriber = Multicaster.getInstance().ior_to_subscriber((String)op.getData().getObj());
				DataWriter dw = new DataWriter();
				dw.addSubscriber(subscriber);
				op.getData().setObj(topic.getData().getObj());
				dw.write(op);
			}
		}
	}
}
